<?php

namespace DaHone;
/**
 * 返回两个特定值之间的随机数支持两边
 * Class Random
 */
class Random
{
    public $start;

    public $end;

    public $res;

    public $startFloat;

    public $endFloat;


    public $times;


    public $float;//小数点位数

    public $zeroEnable = false;

    public function setS($start = 0, $end = 0, int $float = 0, bool $zero = false)
    {
        $start = strval($start);
        $end = strval($end);
        $this->start = $start > $end ? $end : $start;
        $this->end = $start < $end ? $end : $start;
        $this->float = $float;
        $this->zeroEnable = $zero;
        return $this;
    }

    /**
     * 设置小数点后的位数
     * @return $this
     */
    public function setIntAndFloat()
    {
        $startArr = explode('.', $this->start);
        $this->startFloat = isset($startArr[1]) ? $startArr[1] : '0';
        $endArr = explode('.', $this->end);
        $this->endFloat = isset($endArr[1]) ? $endArr[1] : '0';
        return $this;
    }

    /**
     * 设置倍数
     * @return $this
     */
    public function setTimes()
    {
        $this->startFloat;
        $startFloatLen = strlen($this->startFloat);
        $endFloatLen = strlen($this->endFloat);
        $float = ($startFloatLen >= $endFloatLen) ? $startFloatLen : $endFloatLen;
        $this->float = ($this->float >= $float) ? $this->float : $float;
        $this->times = pow(10, $this->float);
        return $this;
    }

    /**
     * 计算小数点之间的随机值
     * @throws \Exception
     */
    public function floatRange()
    {
        while (true) {
            $range = random_int($this->start * $this->times, $this->end * $this->times);
            $this->res = bcdiv($range, $this->times, $this->float);
            if ($this->res == 0 && $this->zeroEnable === false) {
                continue;
            }
            break;
        }
        return $this->res;
    }


    /**
     * 魔术方法
     * @param $start
     * @param $end
     * @param int $float
     * @param bool $zero
     * @return string|null
     * @throws \Exception
     */
    function __invoke($start, $end, $float = 0, $zero = false)
    {
        return (new self())->setS($start, $end, $float, $zero = false)->setIntAndFloat()->setTimes()->floatRange();
    }
}




